package plus.exp;

import java.util.LinkedList;

import plus.Gripe;
import plus.S_Record;
import plus.Type;
import plus.run.Emit;

public class E_Access extends Exp implements plus.Constraint {
	Exp rec;
	String name;
	int lineNr;
	public E_Access(int lineNr, Exp e, String name) {
		this.rec = e;
		this.name=name;
	}
	Exp call(LinkedList<Exp> es) { return new E_MethodCall(rec, name, es); }
	@Override
	public void threadScope() {
		rec.threadScope();
		rec.checkThread();
		type = Type.variable();
		Gripe.lineNr = lineNr;
		Gripe.context = this;
		rec.type.chase().unifyField(name, type, lineNr);
	}
	@Override
	public void threadAssign() { threadScope(); }
	@Override String impliedName() { return name; }
	@Override public boolean solve() {
		return rec.type.chase().unifyField(name, type, lineNr);
	}

	@Override String aThis() { return "a field of a record"; }
	@Override public String toString() { return "access to field '"+name+"' of "+rec.aThis(); }
	@Override
	public void compileAssign(Exp rhs) {
		rec.compilePush();
		rhs.compilePush();
		Emit.storeIndex(fieldOffset());
	}

	@Override
	public void compilePush() {
		rec.compilePush();
		Emit.loadIndex(fieldOffset());
	}

	private int fieldOffset() {
		S_Record sol = (S_Record)rec.type.chase().getSolution();
		return sol.indexOfField(name);
	}

}
